<!--
本组件实现手动上传多个图片文件到图书馆服务器的功能，常用于文章内容页上传多个图片
本组件定义的输出值的方法名为 @setUploadResult="getUploadResult($event)"
调用本组件时，父组件中定义一个名称为 getUploadResult(e) 的方法
e为本组件返回的上传结果，格式如下：
[
  'https://xzqtsg.net/api-public/file/image/{uuid}',
  'https://xzqtsg.net/api-public/file/image/{uuid}'
]
-->
<template>
  <div class="wrapper-uploader">
    <el-button icon="UploadFilled" size="small" type="success" @click="flagDialogUpload = true">上传多图</el-button>
    <!--选择多图上传 Dialog-->
    <el-dialog
      v-model="flagDialogUpload"
      title="选择本地图片上传到服务器，一次最多选 5 张图片，每张图片不能超过 5 M！"
      width="70%"
    >
      <el-upload
        ref="theUploader"
        :auto-upload="false"
        action="void"
        :data="paramsJson"
        :headers="headerJwt"
        :class="{ hide: flagHideUploader }"
        :show-file-list="true"
        :file-list="selectedFileList"
        list-type="picture-card"
        :limit="5"
        multiple
        :on-exceed="onExceed"
        :on-preview="onPreview"
        :on-change="onChange"
        :on-remove="onRemove"
      >
        <el-icon><Plus /></el-icon>
      </el-upload>
      <template #footer>
        <el-button @click="flagDialogUpload = false">取消</el-button>
        <el-button @click="onClear()">清空</el-button>
        <el-button ref="refBtnUpload" type="primary" @click="submitUpload()">确定上传</el-button>
      </template>
    </el-dialog>
    <!--图像预览 Dialog-->
    <el-dialog v-model="flagDialogPreview">
      <img style="width: 100%" :src="urlImagePreview" alt="" />
    </el-dialog>
  </div>
</template>

<script>
import { getJwtFromCookie } from '@/utils/jwt'
import { getLStorageObj } from '@/utils/web-storage'
import { validUploadFiles } from '@/utils/file'
import { toastSuccess, toastError } from '@/utils/toast'

import store from '@/store'
import router from '@/router'
import { defineComponent, ref, onMounted, computed } from 'vue'
export default defineComponent({
  name: 'UploadImagesCom',
  props: {
    adminId: {
      type: Number,
      default: 0,
    },
    taskId: {
      type: Number,
      default: 0,
    },
  },
  emit: ['update:setUploadResult'],
  setup(props, { emit }) {
    const uploadConfig = ref()
    const urlPrefixShowImg = ref(process.env.VUE_APP_URL_UPLOAD_SHOW_UUID)
    // const urlPrefixShowIIS = ref(process.env.VUE_APP_BASE_DOMAIN_SHOW_UPLOAD_FILE_PREFIX)
    // 显示上传框
    const flagDialogUpload = ref(false)
    // 显示图片预览框
    const flagDialogPreview = ref(false)
    // 预览图片用到的变量
    const urlImagePreview = ref('')
    // 当选择满了图片后隐藏选择图片按钮要用到的判断变量
    const flagHideUploader = ref(false)
    // 上传成功后的服务器返回信息存到此变量中
    const uploadResultList = ref([])
    // 选中的文件列表，注意：这个变量不是双向绑定的，要在onChange方法里对其进行赋值
    const selectedFileList = ref([])
    const refBtnUpload = ref(null)

    const headerJwt = computed(() => {
      return { authorization: 'Bearer ' + getJwtFromCookie() }
    })
    const paramsJson = computed(() => {
      return { AdminId: props.adminId, TaskId: props.taskId, FormData: null }
    })

    // 获取上传设置
    const getConfigUpload = () => {
      uploadConfig.value = getLStorageObj('UploadConfig')
      // 检验上传配置是否已设置，如果没有，跳回登录页
      if (!uploadConfig.value) {
        toastError('读取上传配置出错！请重新登录')
        router.push({ path: '/login' })
      }
    }

    // 在onChange前执行，文件超出个数限制时的钩子，这个限制是 limit 属性设定的
    const onExceed = () => {
      // console.log('onExceed files', files)
      // console.log('onExceed fileList', fileList)
      // files 是选中的硬盘上的文件数组
      // fileList 是组件里已选中的文件数组
      // 已选中的文件数组长度+选中的硬盘上的文件数组的长度>limit属性值，才表示超出个数限制
      toastError('一次最多上传 5 个文件')
    }
    // 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用，移除文件时不会调用
    // 经过调试，选了3个文件，这个方法会执行3次
    // 要执行多次，所以验证文件不放在这里
    const onChange = (file, fileList) => {
      // console.log('onChange file', file)
      selectedFileList.value = validUploadFiles(fileList, uploadConfig.value.allowedExtImg, uploadConfig.value)
      // console.log('onchange selectedFileList', selectedFileList.value)
      flagHideUploader.value = fileList.length >= 5
    }
    // 文件列表移除文件时的钩子，此时无需返回值给父组件
    const onRemove = (file, fileList) => {
      // console.log('onRemove file', file)
      // console.log('onRemove fileList', fileList)
      selectedFileList.value = fileList
      flagHideUploader.value = fileList.length >= 5
    }
    // 预览文件
    const onPreview = (file) => {
      console.log('onPreview file:', file)
      urlImagePreview.value = file.url
      flagDialogPreview.value = true
    }
    // 清空选中的要上传的文件
    const onClear = () => {
      selectedFileList.value = []
    }
    // 手动上传，要点击上传按钮才上传，并且 onBeforeUpload、onSuccess 都不执行
    const submitUpload = () => {
      refBtnUpload.value.disable = true
      // 验证是否为空
      if (selectedFileList.value.length === 0) {
        toastError('请选择要上传的文件!')
        return false
      }
      let formData = new FormData()
      selectedFileList.value.forEach((file) => {
        formData.append('files', file.raw)
      })
      paramsJson.value.FormData = formData
      store
        .dispatch('sys_ul_file/uploadFileMulti', paramsJson.value)
        .then((response) => {
          console.log('多图片上传成功后的 response：', response)
          const resultList = response
          for (let i = 0; i < resultList.length; i++) {
            uploadResultList.value.push(urlPrefixShowImg.value + resultList[i].uuid)
          }
          toastSuccess('文件上传成功!')
          // 将结果返回给调用此组件的父组件
          returnUploadResult(uploadResultList.value)
          // console.log('uploadResultList.value', uploadResultList.value)
          // 清空已选文件列表
          selectedFileList.value = []
          // 清空已上传的文件列表
          uploadResultList.value = []
          // 显示选择本地文件按钮
          flagHideUploader.value = false
          // 关闭上传dialog
          flagDialogUpload.value = false
          refBtnUpload.value.disable = false
        })
        .catch((error) => {
          console.log('上传多文件时API返回错误:', error)
          toastError(error)
          // 将结果返回给调用此组件的父组件
          returnUploadResult([])
          flagDialogUpload.value = true
          refBtnUpload.value.disable = false
        })
    }
    const returnUploadResult = (val) => {
      console.log('returnUploadResult 的 val：', val)
      // 调用本组件时，本组件实例添加一个方法 @setUploadResult="getUploadResult($event)"
      // 父组件中定义一个名称为 getUploadResult 的方法，方法的参数值就是这里返回的上传结果
      emit('setUploadResult', val)
    }

    onMounted(() => {
      getConfigUpload()
      // 组件初始化时获得当前上传文件的系统设置
      uploadConfig.value = getLStorageObj('UploadConfig')
    })

    return {
      uploadConfig,
      urlPrefixShowImg,
      flagDialogUpload,
      flagDialogPreview,
      flagHideUploader,
      urlImagePreview,
      uploadResultList,
      selectedFileList,
      headerJwt,
      paramsJson,
      refBtnUpload,
      getConfigUpload,
      onExceed,
      onChange,
      onRemove,
      onPreview,
      onClear,
      submitUpload,
      returnUploadResult,
    }
  },
})
</script>

<style lang="scss" scoped>
:deep(.el-upload--picture-card) {
  width: 60px;
  height: 60px;
  line-height: 60px;
  padding-top: 3px;
}
.hide {
  :deep(.el-upload--picture-card) {
    display: none;
  }
}
</style>
